﻿using System;
using System.Timers;
using System.Runtime.InteropServices;
using RxjhServer.HelperTools;

namespace RxjhServer.Network
{
    public class NetState : IDisposable
    {
        public int Key2 = 2138432278;

        public bool 在线;

        public bool 登陆;

        public bool 加密;

        private TcpServer Server;

        public DateTime Ljtime = DateTime.Now;

        private IntPtr _ConnId = IntPtr.Zero;

        private int _WorldId;

        private bool _挂机;

        private Players _Player;

        public ByteQueue m_Buffer;

        private bool m_Running;

        private string m_ToString;

        public byte[] g_cur_key = new byte[]
        {
            169,
            39,
            131,
            1,
            178,
            108,
            65,
            151,
            201,
            54,
            21,
            170,
            85,
            60,
            157,
            51,
            187,
            222,
            37,
            137,
            119,
            122,
            183,
            153,
            204,
            218,
            35,
            67,
            103,
            124,
            55,
            144
        };

        public bool 版本验证;

        private System.Timers.Timer _自动断开;

        public int dwStop;

        private string _port = string.Empty;

        public bool 退出;

        public IntPtr ConnId
        {
            get
            {
                return this._ConnId;
            }
            set
            {
                this._ConnId = value;
            }
        }

        public int WorldId
        {
            get
            {
                return this._WorldId;
            }
            set
            {
                this._WorldId = value;
            }
        }
        private string _绑定帐号 = string.Empty;
        public bool 挂机
        {
            get
            {
                return this._挂机;
            }
            set
            {
                this._挂机 = value;
            }
        }
        public string 绑定帐号
        {
            get
            {
                return this._绑定帐号;
            }
            set
            {
                this._绑定帐号 = value;
            }
        }
        public Players Player
        {
            get
            {
                return this._Player;
            }
            set
            {
                this._Player = value;
            }
        }

        private ByteQueue mBuffer
        {
            get
            {
                return this.m_Buffer;
            }
        }

        public bool Running
        {
            get
            {
                return this.m_Running;
            }
            set
            {
                this.m_Running = value;
            }
        }

        public override string ToString()
        {
            return this.m_ToString;
        }

        public System.Timers.Timer 自动断开
        {
            get
            {
                return this._自动断开;
            }
            set
            {
                this._自动断开 = value;
            }
        }

        public string port
        {
            get
            {
                return this._port;
            }
            set
            {
                this._port = value;
            }
        }
        public void delWorldIdd(int WId)
        {
            try
            {
                if (this.InList(WId))
                {
                    World.list[WId] = null;
                    World.list.Remove(WId);
                }
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "delWorldIdd()出错",
                    this.WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex.Message
                }));
            }
        }
        public void delWorldIdd()
        {
            try
            {
                World.list.Remove(this._WorldId);
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "delWorldIdd()出错",
                    this._WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex.Message
                }));
            }
        }

        ~NetState()
        {
        }
        public void DisposedOffline()
        {
            try
            {
                int num = this.ConnId.ToInt32();
                int worldId = this.WorldId;
                string text = this.ToString();
                this.挂机 = false;
                this.退出 = true;
                this.Player.是否人物离线挂机 = false;
                this.m_Running = false;
                if (this.m_Buffer != null)
                {
                    this.m_Buffer.Dispose();
                    this.m_Buffer = null;
                }
                if (this.自动断开 != null)
                {
                    this.自动断开.Enabled = false;
                    this.自动断开.Close();
                    this.自动断开.Dispose();
                    this.自动断开 = null;
                }
                this.IDout();
                if (this.Player != null)
                {
                    this.Player.Logout();
                    this.Player.Dispose();
                }
                Players players;
                if (World.allConnectedChars.TryGetValue(this.WorldId, out players))
                {
                    World.allConnectedChars.Remove(this.WorldId);
                }
                this.Player = null;
                this.delWorldIdd(this.WorldId);
                int num2 = 18;
                Form1.WriteLine(3, string.Concat(new object[]
                {
                    "退出挂机 连接ID[",
                    num,
                    "]人物全服ID[",
                    worldId,
                    "] IP地址[",
                    text,
                    "] ExceStep:",
                    num2
                }));
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    " ProcessDisposedOffline()出错",
                    this.WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex.Message
                }));
            }
        }
        public NetState(ClientInfo Ci)
        {
            try
            {
                if (World.登陆器模式 == 2)
                {
                    g_cur_key = new byte[]
       {
            4,
            55,
            194,
            8,
            236,
            235,
            63,
            151,
            52,
            131,
            91,
            17,
            67,
            248,
            106,
            144,
            193,
            231,
            211,
            232,
            92,
            237,
            241,
            255,
            89,
            139,
            13,
            129,
            51,
            65,
            89,
            137
       };
                }
                this._ConnId = Ci.ConnId;
                this.Server = Ci.Server;
                this.Ljtime = DateTime.Now;
                this.挂机 = false;
                this.m_Buffer = new ByteQueue();
                this.m_Running = false;
                this.m_ToString = Ci.IpAddress;
                this._port = Ci.Port.ToString();
                this._WorldId = Ci.WorldId;
                if (this._WorldId < 300)
                {
                    Form1.WriteLine(1, string.Concat(new object[]
                    {
                        this._WorldId,
                        " 断开卡号连接1 ",
                        this.m_ToString,
                        ":",
                        this._port
                    }));
                    this.Server.Disconnect(this._ConnId, true);
                }
                else
                {
                    using (new Lock(World.lockLogin, "客户端连接"))
                    {
                        if (this.InList(this._WorldId))
                        {
                            Form1.WriteLine(1, string.Concat(new object[]
                            {
                                this._WorldId,
                                " 断开卡号连接2 ",
                                this.m_ToString,
                                ":",
                                this._port
                            }));
                            this.Server.Disconnect(this._ConnId, true);
                            return;
                        }
                        World.list.Add(this._WorldId, this);
                        this.Player = new Players(this);
                    }
                    this._自动断开 = new System.Timers.Timer((double)World.版本验证时间);
                    this._自动断开.Elapsed += new ElapsedEventHandler(this.自动断开事件);
                    this._自动断开.AutoReset = true;
                    this._自动断开.Enabled = true;
                    Form1.WriteLine(3, string.Concat(new object[]
                    {
                        "连接 连接ID[",
                        this._ConnId.ToInt32(),
                        "]-全服ID[",
                        this._WorldId,
                        "]-IP地址[",
                        this.m_ToString,
                        ":",
                        this._port,
                        "]"
                    }));
                }
            }
            catch (Exception ex)
            {
                this.Server.Disconnect(this._ConnId, true);
                Form1.WriteLine(3, string.Concat(new object[]
                {
                    this._WorldId,
                    " 初始化客户端连接出错 ",
                    this.m_ToString,
                    ":",
                    this._port,
                    "|",
                    ex.Message
                }));
            }
        }

        private bool InList(int key)
        {
            return World.list.ContainsKey(key);
        }

        private void 自动断开事件(object source, ElapsedEventArgs e)
        {
            if (!this.版本验证)
            {
                Form1.WriteLine(1, this._WorldId + " 自动断开事件 " + this.ToString());
                this.Dispose(true);
            }
            if (this._自动断开 != null)
            {
                this._自动断开.Enabled = false;
                this._自动断开.Close();
                this._自动断开.Dispose();
                this._自动断开 = null;
            }
        }

        private void reflashClient()
        {
            ClientInfo clientInfo = new ClientInfo();
            clientInfo.ConnId = this._ConnId;
            clientInfo.IpAddress = this.ToString();
            clientInfo.Port = ushort.Parse(this.port);
            clientInfo.Server = this.Server;
            clientInfo.WorldId = this._WorldId;
            clientInfo.Client = this;
            this.Server.SetConnectionExtra(this.ConnId, clientInfo);
        }

        public void Start()
        {
            if (this.Player != null)
            {
                this.m_Running = true;
                this.reflashClient();
            }
        }
        [DllImport("rxjhDeBuf.dll")]
        public static extern void Decrypt([Out, MarshalAs(UnmanagedType.LPArray)] byte[] A_0, int A_1);
        private void Decrypta(ref byte[] buff)
        {

            byte b = 0;
            for (int i = 0; i < buff.Length - 6; i++)
            {
                byte b2 = buff[4 + i];
                buff[4 + i] = (byte)(buff[4 + i] ^ this.g_cur_key[i % 32] ^ b);
                b = b2;
            }
        }

        public void IDout()
        {
            try
            {
                if (this.Player != null)
                {
                    World.conn.发送(string.Concat(new object[]
                    {
                        "用户登出|",
                        this.Player.Userid,
                        "|",
                        World.服务器ID
                    }));
                }
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "IDout()出错",
                    this._WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex.Message
                }));
            }
        }

        public void HandleReceive(NetState ns)
        {
            try
            {
                if (this.mBuffer != null && this.mBuffer.Length > 0)
                {
                    using (new Lock(this.mBuffer, "HandleReceive"))
                    {
                        int length = this.mBuffer.Length;
                        while (length > 0 && this.Running && length > 4)
                        {
                            int num = (int)BitConverter.ToInt16(this.mBuffer.GetPacketID(), 0);
                            if (num <= 0)
                            {
                                this.mBuffer.Clear();
                                break;
                            }
                            num += 6;
                            if (length >= num)
                            {
                                byte[] array = new byte[num];
                                this.mBuffer.Dequeue(array, 0, num);
                                length = this.mBuffer.Length;
                                if (170 != array[0] || 85 != array[1])
                                {
                                    this.mBuffer.Clear();
                                    break;
                                }
                                if (array[num - 2] != 85 || array[num - 1] != 170)
                                {
                                    this.mBuffer.Clear();
                                    break;
                                }
                                if (World.是否加密 == 1)
                                {
                                    if (World.登陆器模式 == 1)
                                    {
                                        Decrypta(ref array);
                                    }
                                    else if (World.登陆器模式 == 2)
                                    {
                                        Decrypta(ref array);
                                    }
                                    else if (World.登陆器模式 == 0)
                                    {
                                        byte[] dst = new byte[num - 6];
                                        System.Buffer.BlockCopy(array, 4, dst, 0, dst.Length);
                                        Decrypt(dst, dst.Length);
                                        System.Buffer.BlockCopy(dst, 0, array, 4, dst.Length);

                                    }
                                }
                                
                                byte[] 人物ID_ = new byte[4];
                                Buffer.BlockCopy(array, 5, 人物ID_, 0, 2);
                                int 人物ID = BitConverter.ToInt32(人物ID_, 0);
                                if (人物ID < 40000)
                                {
                                    Buffer.BlockCopy(BitConverter.GetBytes(WorldId), 0, array, 5, 2);
                                }
                                
                                //Buffer.BlockCopy(BitConverter.GetBytes(WorldId), 0, array, 5, 2);
                                /*
                                string rec = Converter.ToString(array);
                                int aaa = BitConverter.ToInt16(array, 7);
                                if (aaa == 176)
                                    Form1.WriteLine(1, "长度" + array.Length + "|" + rec + "");
                                */
                                this.Player.ManagePacket(array, array.Length);
                            }
                            else
                            {
                                if (170 != this.mBuffer.m_Buffer[0] && 85 != this.mBuffer.m_Buffer[1])
                                {
                                    this.mBuffer.Clear();
                                    break;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "HandleReceive()出错",
                    this._WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex
                }));
                this.Server.Disconnect(this._ConnId, true);
            }
        }

        public void Send(byte[] bytes, int len)
        {
            if (!this.m_Running)
            {
                return;
            }
            this.Server.Send(this._ConnId, bytes, len);
        }

        public void Send单包(byte[] toSendBuff, int len)
        {
            int num = (int)BitConverter.ToInt16(toSendBuff, 9);
            byte[] array = new byte[num + 7];
            Buffer.BlockCopy(toSendBuff, 5, array, 0, array.Length);
            this.Send单包封装发送(array, array.Length);
        }

        private void Send单包封装发送(byte[] toSendBuff, int length)
        {
            byte[] array = new byte[length + 15];
            array[0] = 170;
            array[1] = 85;
            Buffer.BlockCopy(BitConverter.GetBytes(length + 9), 0, array, 2, 2);
            Buffer.BlockCopy(toSendBuff, 0, array, 5, length);
            array[array.Length - 2] = 85;
            array[array.Length - 1] = 170;
            this.Send(array, array.Length);
        }

        public void Send多包(byte[] toSendBuff, int len)
        {
            int num = (int)BitConverter.ToInt16(toSendBuff, 9);
            byte[] array = new byte[num + 6];
            Buffer.BlockCopy(toSendBuff, 5, array, 0, array.Length);
            this.Send多包加密(array, array.Length, 1);
        }

        private void Send多包加密(byte[] toSendBuff, int length, int xl)
        {
            try
            {
                byte[] src;
                int num = this.SendDuopak3(toSendBuff, length, out src);
                byte[] array = new byte[num + 8];
                Buffer.BlockCopy(BitConverter.GetBytes(192), 0, array, 0, 2);
                Buffer.BlockCopy(BitConverter.GetBytes(num + 4), 0, array, 2, 2);
                Buffer.BlockCopy(BitConverter.GetBytes(num), 0, array, 4, 2);
                Buffer.BlockCopy(BitConverter.GetBytes(length), 0, array, 6, 2);
                Buffer.BlockCopy(src, 0, array, 8, num);
                this.Send多包封装发送(array, array.Length, xl);
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "Send()_Send多包加密发送错误",
                    this._WorldId,
                    "|",
                    ex.Message
                }));
            }
        }

        private void Send多包封装发送(byte[] toSendBuff, int length, int xl)
        {
            byte[] array = new byte[length + 17];
            array[0] = 170;
            array[1] = 85;
            Buffer.BlockCopy(BitConverter.GetBytes(length + 11), 0, array, 2, 2);
            Buffer.BlockCopy(BitConverter.GetBytes(xl), 0, array, 5, 2);
            Buffer.BlockCopy(toSendBuff, 0, array, 7, length);
            array[array.Length - 2] = 85;
            array[array.Length - 1] = 170;
            this.Send(array, array.Length);
        }

        public void Offline()
        {
            if (this.Server.Disconnect(this._ConnId, true))
            {
                this.退出 = true;
                this.挂机 = true;
                Form1.WriteLine(3, this._WorldId + " 离线挂机 " + this.ToString());
                return;
            }
            Form1.WriteLine(3, this._WorldId + " 离线挂机错误 " + this.ToString());
        }

        public void Disposed()
        {
            int num = 0;
            try
            {
                this._ConnId.ToInt32();
                //this.ToString() + ":" + this.port;
                this.挂机 = false;
                this.退出 = true;
                this.m_Running = false;
                num = 4;
                if (this.m_Buffer != null)
                {
                    this.m_Buffer.Dispose();
                    this.m_Buffer = null;
                }
                num = 5;
                if (this._自动断开 != null)
                {
                    this._自动断开.Enabled = false;
                    this._自动断开.Close();
                    this._自动断开.Dispose();
                    this._自动断开 = null;
                }
                num = 6;
                if (!World.m_Disposed.Contains(this))
                {
                    World.m_Disposed.Enqueue(this);
                }
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    " ProcessDisposed()出错",
                    this._WorldId,
                    "|",
                    this.ToString(),
                    "|",
                    num,
                    " ",
                    ex.Message
                }));
            }
        }
        public void logout(SocketOperation enOperation, int errorCode)
        {
            int num = 0;
            try
            {
                num = 1;
                NetState netState;
                if (World.list.TryGetValue(this.WorldId, out netState))
                {
                    num = 2;
                    if (!this.挂机)
                    {
                        num = 3;
                        int num2 = this.ConnId.ToInt32();
                        int worldId = this.WorldId;
                        string text = this.ToString() + ":" + this.port;
                        this.挂机 = false;
                        this.退出 = true;
                        this.m_Running = false;
                        num = 4;
                        if (this.m_Buffer != null)
                        {
                            this.m_Buffer.Dispose();
                            this.m_Buffer = null;
                        }
                        num = 5;
                        if (this.自动断开 != null)
                        {
                            this.自动断开.Enabled = false;
                            this.自动断开.Close();
                            this.自动断开.Dispose();
                            this.自动断开 = null;
                        }
                        //if (!World.m_Disposed.Contains(this))
                        //{
                        //    World.m_Disposed.Enqueue(this);
                        //}
                        num = 6;
                        if (this.在线)
                        {
                            this.IDout();
                            num = 7;
                        }
                        num = 8;
                        if (this.Player != null)
                        {
                            num = 9;
                            //if (!this.Player.退出中)
                            //{
                            //this.Player.退出中 = true;
                                num = 10;
                                this.Player.Logout();
                                num = 11;
                            //}
                            num = 12;
                            //this.Player.OpClient(1);
                            this.Player.Dispose();
                            num = 13;
                        }
                        num = 14;
                        Players players;
                        if (World.allConnectedChars.TryGetValue(this.WorldId, out players))
                        {
                            num = 15;
                            World.allConnectedChars.Remove(this.WorldId);
                            num = 16;
                        }
                        num = 17;
                        this.Player = null;
                        this.delWorldIdd(this.WorldId);
                        num = 18;
                        Form1.WriteLine(3, string.Concat(new object[]
                        {
                            "退出 连接ID[",
                            num2,
                            "]人物全服ID[",
                            worldId,
                            "] IP地址[",
                            text,
                            "] ExceStep:",
                            num
                        }));
                    }
                }
            }
            catch
            {
                Form1.WriteLine(3, "退出错误 ExceStep:" + num);
            }
        }
        //public void logout(SocketOperation enOperation, int errorCode)
        //{
        //    try
        //    {
        //        NetState netState;
        //        if (World.list.TryGetValue(this._WorldId, out netState) && !this.挂机)
        //        {
        //            this.Disposed();
        //        }
        //    }
        //    catch
        //    {
        //    }
        //}

        public void Dispose()
        {
            this.Dispose(true);
        }

        private void Dispose(bool flush)
        {
            try
            {
                this.Server.Disconnect(this._ConnId, true);
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    " Dispose()出错",
                    this._WorldId,
                    "|",
                    this.ToString(),
                    " ",
                    ex.Message
                }));
            }
            //this.Disposed();
        }

        public void SendPak(发包类 pak, int id, int wordid)
        {
            try
            {
                byte[] array = pak.ToArray2(id, wordid);
                this.Send多包加密(array, array.Length, 1);
            }
            catch (Exception)
            {
            }
        }

        private int SendDuopak3(byte[] 进包, int 进包长, out byte[] packetBuffer)
        {
            packetBuffer = new byte[进包长 + 进包长 / 32 + 1];
            int num = 0;
            int num2 = 0;
            int i = 6;
            int num3 = i - 1;
            int num4 = 0;
            int num5 = 0;
            int num6 = 0;
            try
            {
                while (i <= 进包长)
                {
                    while (num3 > 1 && i - num3 < 255)
                    {
                        while (num4 < 255 && num3 + num4 < 进包长 && i + num4 < 进包长)
                        {
                            if (进包[i + num4] == 进包[num3 + num4])
                            {
                                num5++;
                                num4++;
                            }
                            else
                            {
                                if (num5 < 3)
                                {
                                    num5 = 0;
                                    break;
                                }
                                if (进包[i] == 进包[num3 - 1] && i - num3 < 254)
                                {
                                    num6 = 1;
                                    break;
                                }
                                this.OneByte(i, num3, num4, num5, 进包, ref num2, ref num, ref packetBuffer);
                                i = num2;
                                num3 = num2;
                                num6 = 0;
                                num5 = 0;
                                break;
                            }
                        }
                        if (num5 >= 3 && (进包[i] != 进包[num3 - 1] || num6 == 0))
                        {
                            this.OneByte(i, num3, num4, num5, 进包, ref num2, ref num, ref packetBuffer);
                            i = num2;
                            num3 = num2;
                            num6 = 0;
                        }
                        num4 = 0;
                        num5 = 0;
                        num3--;
                    }
                    num3 = i;
                    i++;
                }
                if (num2 < 进包长)
                {
                    int num7 = 进包长 - num2;
                    if (num7 > 32)
                    {
                        int num8 = 0;
                        byte[] array = new byte[num7];
                        Buffer.BlockCopy(进包, num2, array, 0, array.Length);
                        byte[] array2 = this.SendDuopak(array, array.Length, out num8);
                        if (num == 0)
                        {
                            packetBuffer = new byte[array2.Length];
                        }
                        Buffer.BlockCopy(array2, 0, packetBuffer, num, num8);
                        num += num8;
                        num2 += num7;
                    }
                    else if (num7 > 0)
                    {
                        packetBuffer[num++] = (byte)(进包长 - num2 - 1);
                        Buffer.BlockCopy(进包, num2, packetBuffer, num, 进包长 - num2);
                        num += 进包长 - num2;
                        num2 += 进包长 - num2;
                    }
                }
            }
            catch (Exception value)
            {
                Console.WriteLine(value);
            }
            return num;
        }

        private void OneByte(int j, int i, int n, int x, byte[] 进包, ref int 进包处理长, ref int 出包长, ref byte[] packetBuffer)
        {
            int num = j - 进包处理长;
            if (num > 32)
            {
                int num2 = 0;
                byte[] array = new byte[num];
                Buffer.BlockCopy(进包, 进包处理长, array, 0, array.Length);
                byte[] src = this.SendDuopak(array, array.Length, out num2);
                Buffer.BlockCopy(src, 0, packetBuffer, 出包长, num2);
                出包长 += num2;
                进包处理长 += num;
            }
            else if (num > 0)
            {
                packetBuffer[出包长++] = (byte)(num - 1);
                Buffer.BlockCopy(进包, 进包处理长, packetBuffer, 出包长, j - 进包处理长);
                出包长 += j - 进包处理长;
                进包处理长 += j - 进包处理长;
            }
            int num3 = x - 2;
            if (num3 < 7)
            {
                packetBuffer[出包长++] = (byte)(num3 << 5);
                int num4 = j - i - 1;
                packetBuffer[出包长++] = (byte)num4;
            }
            else
            {
                int num5 = 7;
                packetBuffer[出包长++] = (byte)(num5 << 5);
                int num6 = x - 2 - 7;
                packetBuffer[出包长++] = (byte)num6;
                int num7 = j - i - 1;
                packetBuffer[出包长++] = (byte)num7;
            }
            进包处理长 += x;
        }

        private byte[] SendDuopak(byte[] toSendBuff, int length, out int outlength)
        {
            byte[] result;
            try
            {
                int num = 10;
                int num2 = length / num;
                while (length - num2 * num > 0 && length - num2 * num < 2)
                {
                    num++;
                    num2 = length / num;
                }
                if (length % num > 0)
                {
                    num2++;
                }
                byte[] array = new byte[length + num2];
                int num3 = 0;
                int num4 = 0;
                int num5 = num;
                do
                {
                    if (num3 + num5 >= length)
                    {
                        num5 = length - num3;
                        array[num4] = (byte)(num5 - 1);
                        Buffer.BlockCopy(toSendBuff, num3, array, num4 + 1, num5);
                        num3 += num5;
                        num4 += num5 + 1;
                    }
                    else
                    {
                        array[num4] = (byte)(num5 - 1);
                        Buffer.BlockCopy(toSendBuff, num3, array, num4 + 1, num5);
                        num3 += num5;
                        num4 += num5 + 1;
                        num5 = num;
                    }
                }
                while (num3 < length);
                outlength = num4;
                result = array;
            }
            catch (Exception ex)
            {
                Form1.WriteLine(1, string.Concat(new object[]
                {
                    "Send()SendDuopak",
                    this._WorldId,
                    "|",
                    ex.Message
                }));
                outlength = length;
                result = toSendBuff;
            }
            return result;
        }
    }
}
